package helpers;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.channels.Channels;
import java.util.Collections;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileReadChannel;
import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.FileServiceFactory;
import com.google.appengine.api.files.FileWriteChannel;

import entities.Page;

public class FileHelper {
	
	public static void saveCurrentPage(Page currentPage )
	{
			FileHelper.savePage(currentPage);
			
			
	}
	public static Page getPageByFileName(String filename) throws IOException
	{
		Cache cache=null;
    	try {
		    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
		} catch (CacheException e1) {
		   e1.printStackTrace();
		}
		
		
		
		if(cache!=null&&cache.containsKey(filename))
		{
			return (Page)cache.get(filename)	;
		}
		else
		{
			
			String key = DataStoreHelper.getKeyFileName(filename);
			if(key==null)
			{
				return null;
			}
			FileService fileService = FileServiceFactory.getFileService();
			
			AppEngineFile file=fileService.getBlobFile(new BlobKey(key));
			FileReadChannel readChannel = fileService.openReadChannel(file, false);
			GZIPInputStream gzipis = new GZIPInputStream(Channels.newInputStream(readChannel));
			ObjectInputStream ooi = new ObjectInputStream(gzipis);
			Page page=null;
			try {
				page = (Page)ooi.readObject();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(cache!=null)
			{
				cache.put(filename, page);
			}
			return page;
		}
		
	}
	public static Page getPageByKey(String key) throws ClassNotFoundException, IOException
	{
		Cache cache=null;
    	try {
		    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
		} catch (CacheException e1) {
		   e1.printStackTrace();
		}
		
		
		
		if(cache!=null&&cache.containsKey(key))
		{
			return (Page)cache.get(key)	;
		}
		else
		{
			
			
			FileService fileService = FileServiceFactory.getFileService();
			
			AppEngineFile file=fileService.getBlobFile(new BlobKey(key));
			FileReadChannel readChannel = fileService.openReadChannel(file, false);
			ObjectInputStream ooi = new ObjectInputStream(Channels.newInputStream(readChannel));
			Page page = (Page)ooi.readObject();
			if(cache!=null)
			{
				cache.put(key, page);
			}
			return page;
		}
		
	}
	
	public static String savePage(Page page) {
		FileService fileService = FileServiceFactory.getFileService();
		
		AppEngineFile file;
		try {
			file = fileService.createNewBlobFile("text/html",page.getUrl());
			
			
		FileWriteChannel writeChannel = fileService
				.openWriteChannel(file, true);
		GZIPOutputStream gzipos = new GZIPOutputStream(Channels.newOutputStream(writeChannel)) {
			 
		            {
			                def.setLevel(Deflater.BEST_COMPRESSION);
			           }
			       };

		ObjectOutputStream oos = new ObjectOutputStream(gzipos);
		oos.writeObject(page);
		oos.flush();
		oos.close();
		// Now finalize
		writeChannel.closeFinally();
		
		Cache cache=null;
    	try {
		    cache = CacheManager.getInstance().getCacheFactory().createCache(Collections.emptyMap());
		} catch (CacheException e1) {
		   e1.printStackTrace();
		}
		String cachePrefix="datastore_";
		String key = fileService.getBlobKey(file).getKeyString();
		if(cache!=null)
		{
			cache.put(page.getUrl(), page);
			cache.put(cachePrefix+page.getUrl(), key);
		}
		return key;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
	}

	
}
